A task is a set of computer-executable instructions that when performed process data, such as reading, manipulating, and/or writing data. Traditionally, when a task is started, a thread is created to perform the task, and when the task has ended, the thread is terminated. A thread is the lowest-level execution of a set of instructions (i.e., the execution of a task), where a number of threads may, for instance, be concurrently performed to execute a process of a computer program, where a process is different than a thread, and may encompass one or more concurrently executing and/or non-concurrently executing threads.
A difficulty with creating a thread when a task is to be performed and terminating the thread when the task has ended is that a certain amount of overhead is needed to create and terminate (i.e., destroy) threads. A solution to this approach is known as thread pooling. In thread pooling, a pool of threads are initially created and remain in existence (i.e., are not terminated or destroyed), asynchronously with the execution of tasks. When a task has to be executed, an existing available thread is selected from the pool to perform the task. When the task has ended, the thread in question is not terminated, but rather returns to the pool as an available thread.
A problem with thread pooling, however, is that it substantially prevents the ability to detect when a task has started or ended. Generally, the starting of a task can be detected when a thread is created to execute the task, and the ending of the task can be detected when the task that was created to execute the task has been terminated. However, in thread pooling, threads are not created and destroyed synchronously with the execution of the tasks. This means that it can be difficult to detect when a given task has started or ended. For this and other reasons, there is a need for the present invention.